package org.etherframework.tests.features.wiring
{
	import org.etherframework.core.EtherConfig;
	import org.etherframework.common.wire.IWire;
	import org.etherframework.common.wire.IWiring;
	import org.etherframework.core.IModule;
	import org.etherframework.tests.features.wiring.config.ConfigWithCustomProcessor;
	import org.etherframework.tests.features.wiring.models.NotWirableModel;
	import org.etherframework.tests.features.wiring.models.NotifiableWirableModel;
	import org.etherframework.tests.features.wiring.models.PersistentModel;
	import org.etherframework.tests.features.wiring.models.WirableModel;
	import org.etherframework.tests.features.wiring.models.WithoutMetatagsModel;
	import org.etherframework.tests.utils.TestUtility;
	import org.hamcrest.assertThat;
	import org.hamcrest.object.notNullValue;
	import org.hamcrest.object.nullValue;

	public class when_creating_wire
	{	
		private static var _testUtility:TestUtility = new TestUtility();
		private static var _module:IModule;
		private static var _w:IWiring;
		private static var _notWirable:NotWirableModel;
		private static var _wirable:WirableModel;
		private static var _notifiableWirable:NotifiableWirableModel;
		private static var _withoutMetatags:WithoutMetatagsModel;
		private static var _persistentModel:PersistentModel;
		
		[BeforeClass]
		public static function setUpBeforeClass():void
		{
			// Here we use cust config to set custom metatag processor.
			// See MyEtherConfig.
			var config:EtherConfig = new ConfigWithCustomProcessor();
			
			_module = _testUtility.createModuleInfo(config).module;
			
			// Here we create instance of a persistent dependency which is wired
			// automatically by framework during instantiation and kept in its register.
			_module.dependencies.addClass(PersistentModel);
			_persistentModel = _module.ether.dependencies.getInstance(PersistentModel) as PersistentModel;
			_w = _module.wiring;
			
			_notWirable = new NotWirableModel();
			_wirable = new WirableModel();
			_notifiableWirable = new NotifiableWirableModel();
			_withoutMetatags = new WithoutMetatagsModel();
		}
		
		[AfterClass]
		public static function tearDownAfterClass():void
		{
			_testUtility.dispose();
		}
		
		[Test(order=1)]
		public function it_should_be_created():void
		{
			var wire:IWire;
			
			wire = _w.createWire(_notifiableWirable);
			assertThat(wire, notNullValue());
			wire = _w.createWire(_wirable);
			assertThat(wire, notNullValue());
		}
		
		[Test(order=2)]
		public function it_should_return_null_when_target_is_not_wirable():void
		{
			var wire:IWire = _w.createWire(_notWirable);
			assertThat(wire, nullValue());
		}
		
		[Test(order=3)]
		public function it_should_return_null_when_target_does_not_have_defined_metatags():void
		{
			var wire:IWire = _w.createWire(_withoutMetatags);
			assertThat(wire, nullValue());
		}
		
		[Test(order=4)]
		public function it_should_throw_an_error_when_arguments_are_not_valid():void
		{
			var err:Error;
			
			try {
				_w.createWire(null);
			} catch (e:*) {err = e;}
			assertThat(err, notNullValue());
			err = null;
		}
		
		[Test(order=5)]
		public function it_should_throw_an_error_when_wire_already_exists():void
		{
			var err:Error;
			
			try {
				// As this instance implements IPersistent interface it is already 
				// kept by framework and wired, thus it should throw an error when
				// attempting to create another wire for this persistent instance.
				_w.createWire(_persistentModel);
			} catch (e:*) {err = e;}
			assertThat(err, notNullValue());
		}
		
	}
}